package com.egdigital.allzic.service;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.v4.content.LocalBroadcastManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

public abstract class ServiceSoundManagement extends Service {

	private static final String		TAG						= ServiceSoundManagement.class.getSimpleName(); // log
	// binder
	protected final Binder			mBinder					= new PlayerBinder();
	// sys
	private PowerManager.WakeLock	mWakeLock;
	protected AudioManager			mAudioManager;
	protected EventReceiver			mEventReceiver;
	protected PhoneStateListener	mPhoneStateListener;
	protected LocalBroadcastManager	mLocalBroadcastManager;
	// player
	protected static PlayerRadio	mPlayerRadio;															// radio
																											// protected static PlayerPub mPlayerPub;
																											// protected StreamingMode mMode = StreamingMode.PUB; // pub
																											// en Kb/s
	public static int				BIT_RATE				= 64;
	// en Ms
	public static int				BUFFER_AUDIO_CAPACITY	= 1500;
	// en Ms
	public static int				BUFFER_DECODE_CAPACITY	= 700;
	// states
	public boolean					mIsHeadphonePlugged		= false;
	public boolean					mIsCalling				= false;
	public boolean					mIsBaterieLow			= false;
	public boolean					mIsInternetOn			= false;

	@Override
	public void onCreate() {
		super.onCreate();
		// initAudioManager();
		initWakeLock();
		initPhoneStateListener();
		initEventReceiver();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		freeEventReceiver();
		freeWakeLock();
		stopSelf();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return START_STICKY;
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	public class PlayerBinder extends Binder {

		public ServiceSoundManagement getServiceInstance() {
			return ServiceSoundManagement.this;
		}
	}

	/**
	 * wake lock
	 */
	private void initWakeLock() {
		PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
		mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, ServiceSoundManagement.class.getSimpleName());
	}

	protected void takeWakeLock() {
		if (mWakeLock != null && !mWakeLock.isHeld()) {
			mWakeLock.acquire();
		}
	}

	protected void freeWakeLock() {
		if (mWakeLock != null && mWakeLock.isHeld()) {
			mWakeLock.release();
		}
	}

	/**
	 * audio focus
	 */
	private void initAudioManager() {
		mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
		// initialisation du son
		mAudioManager.requestAudioFocus(new AudioManager.OnAudioFocusChangeListener() {

			@Override
			public void onAudioFocusChange(int reason) {
				switch (reason) {
				// LOSS
					case AudioManager.AUDIOFOCUS_LOSS:
						// Lost focus, pause playback
						if (mPlayerRadio != null) {
							if (mPlayerRadio.isStarted()) {
								try {
									mPlayerRadio.stop();
								} catch (Exception e) {
								}
							}
						}
						// if (mPlayerPub != null) {
						// if (mPlayerPub.isStarted()) {
						// try {
						// mPlayerPub.stop();
						// } catch (Exception e) {
						// }
						// }
						// }
						break;
					case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
						break;
					case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
						break;
					// GAIN
					case AudioManager.AUDIOFOCUS_GAIN:
						// Gained focus, start playback
						break;
					case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
						break;
					case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
						break;
				}
			}
		}, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
	}

	/**
	 * event sys
	 */
	protected class EventReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context content, Intent intent) {
			String action = intent.getAction();
			if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(action)) {
				if (mPlayerRadio != null && mPlayerRadio.isStarted()) {
					try {
						mPlayerRadio.stop();
					} catch (Exception e) {
					}
				}
			} else if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
				int state = intent.getIntExtra("state", -1);
				switch (state) {
					case 0:
						mIsHeadphonePlugged = false;
						if (mPlayerRadio != null && mPlayerRadio.isStarted()) {
							try {
								mPlayerRadio.stop();
							} catch (Exception e) {
							}
						}
						break;
					case 1:
						mIsHeadphonePlugged = true;
						if (!mIsCalling) {
							// TODO: start playing again
						}
						break;
				}
			} else if (Intent.ACTION_SCREEN_ON.equals(action)) {
				// User action triggered screen on
			} else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
				// User action triggered screen off
			} else if (Intent.ACTION_BATTERY_LOW.equals(action)) {
				// PAUSE
			} else if (Intent.ACTION_POWER_CONNECTED.equals(action)) {
			} else if (Intent.ACTION_POWER_CONNECTED.equals(action)) {
			}
		}
	}

	private void initEventReceiver() {
		mEventReceiver = new EventReceiver();
		IntentFilter filter = new IntentFilter();
		filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
		filter.addAction(Intent.ACTION_HEADSET_PLUG);
		filter.addAction(Intent.ACTION_SCREEN_ON);
		filter.addAction(Intent.ACTION_SCREEN_OFF);
		filter.addAction(Intent.ACTION_BATTERY_LOW);
		filter.addAction(Intent.ACTION_DIAL);
		filter.addAction(Intent.ACTION_POWER_CONNECTED);
		filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
		registerReceiver(mEventReceiver, filter);
	}

	private void freeEventReceiver() {
		try {
			unregisterReceiver(mEventReceiver);
		} catch (IllegalArgumentException e) {
			// we haven't registered the receiver yet
		}
	}

	/**
	 * event phone
	 */
	private void initPhoneStateListener() {
		mPhoneStateListener = new PhoneStateListener() {

			@Override
			public void onCallStateChanged(int state, String incomingNumber) {
				switch (state) {
					case TelephonyManager.CALL_STATE_RINGING:
						mIsCalling = true;
						if (mPlayerRadio != null && mPlayerRadio.isStarted()) {
							if (mPlayerRadio == null) {
								sendMessageToUI(ServiceStreaming.SERVICE_ERROR);
								return;
							}
							try {
								mPlayerRadio.stop();
							} catch (Exception e) {
							}
						}
						break;
					case TelephonyManager.CALL_STATE_OFFHOOK:
						mIsCalling = false;
						break;
					case TelephonyManager.CALL_STATE_IDLE:
						// TODO: start playing again maybe
						break;
				}
			}
		};
		try {
			TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
			telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
		} catch (SecurityException e) {
		}
	}

	/**
	 * message to send to ui
	 */
	protected void sendMessageToUI(String message) {
		Intent intent = new Intent(message);
		mLocalBroadcastManager.sendBroadcast(intent);
	}

	protected void sendMessageToUI(String message, String key, String value) {
		Intent intent = new Intent(message);
		intent.putExtra(ServiceStreaming.SERVICE_METADATA + "_key", key);
		intent.putExtra(ServiceStreaming.SERVICE_METADATA + "_value", value);
		mLocalBroadcastManager.sendBroadcast(intent);
	}

	protected void sendMessageToUI(String message, String percent) {
		Intent intent = new Intent(message);
		intent.putExtra(ServiceStreaming.SERVICE_PERCENT, percent);
		mLocalBroadcastManager.sendBroadcast(intent);
	}
}
